#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <string.h>
#include <unistd.h>
#include <unordered_map>

std::unordered_map<char, char > getumap(const std::string codebook, const char c)
{
    std::unordered_map<char, char > eumap;
    std::unordered_map<char, char > dumap;
    std::ifstream code_;
    code_.open(codebook);
    if (!code_.is_open())
    {
        std::cout << "open code file failed!!!" << std::endl;
        return eumap;
    }
    char aa;
    int i = 0;
    std::cout << "code file is:" << std::endl;
    while(code_.get(aa))
    {
        char c = 'a' + i;
        std::cout << aa;
        eumap.emplace(c, aa);
        dumap.emplace(aa, c);
        i++;
    }
    std::cout << "-------------------------------------" << std::endl;
    code_.close();
    if (c == 'e')
        return eumap;
    else if (c == 'd')
        return dumap;
}

std::vector<char > getinputV(const std::string inputfile, std::unordered_map<char, char > umap)
{
    std::vector<char > v;
    std::ifstream fin;
    fin.open(inputfile, std::ios_base::in | std::ios_base::binary);
    if (!fin.is_open())
    {
        std::cout << "open input file failed!!!" << std::endl;
        return v;
    }

    // std::string key = std::to_string(i);
    // std::unordered_map<std::string, std::string> ump;
    char cc;
    // int cnt = 0;
    std::cout << "input file is:" << std::endl;
    while (fin.get(cc))
    {
        // 读取的时候遇见空格就会跳跃
        if (cc == ' ')
        {
            std::cout << " ";
            v.push_back(' ');
        }
        else if (umap.find(cc) == umap.end())
        {
            std::cout << cc;
            v.push_back(cc);
        }
        else
        {
            std::cout << cc;
            v.push_back(umap[cc]);
        }
    }
    std::cout << std:: endl;
    std::cout << "-------------------------------------" << std::endl;
    fin.close();
    return v;
}

void outfile(const std::string outputfile, const std::vector<char>& v)
{
    std::ofstream fout;
    fout.open(outputfile, std::ios_base::out | std::ios_base::binary);
    if (!fout.is_open())
    {
        std::cout << "open output file failed!!!" << std::endl;
        return;
    }
    std::cout << "output file is:" << std::endl;
    for (int i = 0; i < v.size(); ++i)
    {
        fout << v.at(i);
        std::cout << v.at(i);
    }
    std::cout << std::endl;
    std::cout << "-------------------------------------" << std::endl;
    fout.close();

}

void encrypt(const std::string codebook, const std::string inputfile, const std::string outputfile)
{

    std::unordered_map<char, char > eumap;
    eumap = getumap(codebook, 'e');

    std::vector<char > v;
    v = getinputV(inputfile, eumap);

    outfile(outputfile, v);
}

void decrypt(std::string codebook, std::string inputfile, std::string outputfile)
{

    std::unordered_map<char, char > dumap;
    dumap = getumap(codebook, 'd');

    std::vector<char > v;
    v = getinputV(inputfile, dumap);

    outfile(outputfile, v);

}

int main(int argc, char *argv[])
{

    std::string ospath = "/home/krasjet/ClionProjects/EnDnLetterSys";
    // char *buf;
    // buf = get_current_dir_name();
    // buf = getcwd(NULL, 0);
    // ospath = buf;


    std::string codemode = argv[1];
    std::string codebook = argv[2];    // "mafile.txt"
    std::string inputfile = argv[3];   // "inputfile.txt"   "encodefile.txt"
    std::string outputfile = argv[4];  // "encodefile.txt"  "decodefile.txt"
    codebook = ospath + "/" + codebook;
    inputfile = ospath + "/" + inputfile;
    outputfile = ospath + "/" + outputfile;
    std::cout << "-------------------------------------" << std::endl;
    std::cout << codebook << std::endl;
    std::cout << inputfile << std::endl;
    std::cout << outputfile << std::endl;
    std::cout << "-------------------------------------" << std::endl;

    if (codemode == "encrypt")
    {
        encrypt(codebook, inputfile, outputfile);
    }
    else if (codemode == "decrypt")
    {
        decrypt(codebook, inputfile, outputfile);
    }
    else
    {
        std::cout << "Please input right codemode!!! " << std::endl;
    }
    return 0;

}